package com.wfh.wfhwx.service.impl;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wfh.wfhwx.exception.BusinessException;
import com.wfh.wfhwx.exception.ErrorCode;
import com.wfh.wfhwx.exception.ThrowUtils;
import com.wfh.wfhwx.model.dto.WxAccountAddDto;
import com.wfh.wfhwx.model.dto.WxAccountPageQueryDto;
import com.wfh.wfhwx.model.dto.WxAccountUpdateDto;
import com.wfh.wfhwx.model.entity.WxAccount;
import com.wfh.wfhwx.service.WxAccountService;
import com.wfh.wfhwx.mapper.WxAccountMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author fenghuanwang
* @description 针对表【wx_account(微信公众号账号)】的数据库操作Service实现
* @createDate 2025-06-18 15:16:35
*/
@Service
@Slf4j
public class WxAccountServiceImpl extends ServiceImpl<WxAccountMapper, WxAccount>
    implements WxAccountService {


    private final WxMpService wxMpService = new WxMpServiceImpl();


    /**
     * 将公众号配置放到运行时服务中
     * @param wxAccount
     */
    private synchronized void addAccountToRuntime(WxAccount wxAccount){
        String appId = wxAccount.getAppId();
        WxMpDefaultConfigImpl config = wxAccount.toWxMpConfig();
        try {
            wxMpService.addConfigStorage(appId, config);
        } catch (NullPointerException e) {
            // 如果没有这个账号，则创建
            log.info("初始化公众号配置");
            Map<String, WxMpConfigStorage> configMap = new HashMap<>(6);
            configMap.put(appId, config);
            wxMpService.setMultiConfigStorages(configMap, appId);
        }
    }

    /**
     * 检查公众号配置是否已经存在运营时中
     * @param appid
     * @return
     */
    private boolean isAccountInRuntime(String appid){
        try {
            return wxMpService.switchover(appid);
        } catch (NullPointerException e) {
            // 未添加任何账号的时候会为null
            return false;
        }
    }

    @Override
    public Long saveAndToRuntime(WxAccountAddDto wxAccountDto, Long userId) {
        // 检查公众号是否已经存在于数据库
        ThrowUtils.throwIf(
                this.count(Wrappers.lambdaQuery(WxAccount.class).eq(WxAccount::getAppId, wxAccountDto.getAppId())) > 0,
                ErrorCode.OPERATION_ERROR,
                "公众号已经存在");
        String appId = wxAccountDto.getAppId();
        synchronized (appId.intern()){
            // 检查公众号是否已经存在于运行时中
            if (this.isAccountInRuntime(appId)){
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "公众号已经存在");
            }
            WxAccount wxAccount = new WxAccount();
            // 对象属性拷贝
            BeanUtils.copyProperties(wxAccountDto, wxAccount);
            wxAccount.setUserId(userId);
            // 保存到数据库
            this.save(wxAccount);
            // 添加到wxjava运行时
            this.addAccountToRuntime(wxAccount);
            return wxAccount.getId();
        }
    }

    /**
     * 删除公众号
     *
     * @param appIds
     * @return
     */
    @Override
    public Boolean delByAppIds(List<String> appIds) {
        // 删除运行时数据
        appIds.forEach(wxMpService::removeConfigStorage);
        // 删除数据库数据
        return this.remove(Wrappers.lambdaQuery(WxAccount.class).in(WxAccount::getAppId, appIds));
    }

    /**
     * 更新公众号
     *
     * @param accountUpdateDto
     * @return
     */
    @Override
    public Boolean updateAndToRuntime(WxAccountUpdateDto accountUpdateDto) {
        // 获取数据库中的公众号信息
        WxAccount wxAccount = this.getById(accountUpdateDto.getId());
        ThrowUtils.throwIf(ObjUtil.isEmpty(wxAccount), ErrorCode.OPERATION_ERROR, "公众号不存在");
        String oldAppId = wxAccount.getAppId();
        // 检查运行时数据是否存在该公众号
        if (!this.isAccountInRuntime(oldAppId)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "公众号不存在");
        }
        // 如果appid为空，就使用原来的appid
        if (StringUtils.isAnyBlank(accountUpdateDto.getAppId())) {
            accountUpdateDto.setAppId(oldAppId);
        }
        // 复制更新数据到实体
        WxAccount wxAccountNew = new WxAccount();
        BeanUtils.copyProperties(accountUpdateDto, wxAccountNew);
        // 更新数据库
        boolean updateById = this.updateById(wxAccountNew);
        if (!updateById) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新失败");
        }
        // 先移除旧的配置
        wxMpService.removeConfigStorage(oldAppId);
        // 添加新的配置
        this.addAccountToRuntime(this.getById(accountUpdateDto.getId()));
        return updateById;
    }

    /**
     * 构建查询参数
     *
     * @param wxAccountPageQueryDto
     * @return
     */
    @Override
    public LambdaQueryWrapper<WxAccount> getQueryWrapper(WxAccountPageQueryDto wxAccountPageQueryDto) {
        // 校验参数
        ThrowUtils.throwIf(ObjUtil.isEmpty(wxAccountPageQueryDto), ErrorCode.PARAMS_ERROR, "参数不能为空");
        LambdaQueryWrapper<WxAccount> queryWrapper = Wrappers.lambdaQuery();
        Long id = wxAccountPageQueryDto.getId();
        String appId = wxAccountPageQueryDto.getAppId();
        String name = wxAccountPageQueryDto.getName();
        Boolean verified = wxAccountPageQueryDto.getVerified();
        String secret = wxAccountPageQueryDto.getSecret();
        String token = wxAccountPageQueryDto.getToken();
        String aesKey = wxAccountPageQueryDto.getAesKey();
        Long userId = wxAccountPageQueryDto.getUserId();
        queryWrapper.eq(ObjUtil.isNotEmpty(id), WxAccount::getId, id)
                .eq(ObjUtil.isNotEmpty(appId), WxAccount::getAppId, appId)
                .like(ObjUtil.isNotEmpty(name), WxAccount::getName, name)
                .eq(ObjUtil.isNotEmpty(verified), WxAccount::getVerified, verified)
                .like(ObjUtil.isNotEmpty(secret), WxAccount::getSecret, secret)
                .like(ObjUtil.isNotEmpty(token), WxAccount::getToken, token)
                .like(ObjUtil.isNotEmpty(aesKey), WxAccount::getAesKey, aesKey)
                .like(ObjUtil.isNotEmpty(userId), WxAccount::getUserId, userId);
        return queryWrapper;
    }

    /**
     * 分页查询公众号
     * @param wxAccountPageQueryDto
     * @return
     */
    @Override
    public Page<WxAccount> pageQuery(WxAccountPageQueryDto wxAccountPageQueryDto) {
        LambdaQueryWrapper<WxAccount> queryWrapper = getQueryWrapper(wxAccountPageQueryDto);
        return this.getBaseMapper().selectPage(new Page<>(wxAccountPageQueryDto.getCurrent(), wxAccountPageQueryDto.getPageSize()), queryWrapper);
    }
}




